package org.codehaus.activemq.util;

import java.net.InetAddress;
import java.net.ServerSocket;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class IdGenerator
{
  private static final Log log = LogFactory.getLog(IdGenerator.class);
  private static final String UNIQUE_STUB;
  private static int instanceCount;
  private static String hostName;
  private String seed;
  private long sequence;

  public static String getHostName()
  {
    return hostName;
  }

  public IdGenerator()
  {
    synchronized (UNIQUE_STUB) {
      this.seed = (UNIQUE_STUB + instanceCount++ + ":");
    }
  }

  public synchronized String generateId()
  {
    return this.seed + this.sequence++;
  }

  public String getSeed()
  {
    return this.seed;
  }

  public static String getSeedFromId(String id)
  {
    String result = id;
    if (id != null) {
      int index = id.lastIndexOf(':');
      if ((index > 0) && (index + 1 < id.length())) {
        result = id.substring(0, index + 1);
      }
    }
    return result;
  }

  public static long getCountFromId(String id)
  {
    long result = -1L;
    if (id != null) {
      int index = id.lastIndexOf(':');

      if ((index > 0) && (index + 1 < id.length())) {
        String numStr = id.substring(index + 1, id.length());
        result = Long.parseLong(numStr);
      }
    }
    return result;
  }

  public static int compare(String id1, String id2)
  {
    int result = -1;
    String seed1 = getSeedFromId(id1);
    String seed2 = getSeedFromId(id2);
    if ((seed1 != null) && (seed2 != null)) {
      result = seed1.compareTo(seed2);
      if (result == 0) {
        long count1 = getCountFromId(id1);
        long count2 = getCountFromId(id2);
        result = (int)(count1 - count2);
      }
    }
    return result;
  }

  static
  {
    String stub = "";
    boolean canAccessSystemProps = true;
    try {
      SecurityManager sm = System.getSecurityManager();
      if (sm != null)
        sm.checkPropertiesAccess();
    }
    catch (SecurityException se)
    {
      canAccessSystemProps = false;
    }
    if (canAccessSystemProps) {
      try {
        hostName = InetAddress.getLocalHost().getHostName();
        ServerSocket ss = new ServerSocket(0);
        stub = "ID:" + hostName + "-" + ss.getLocalPort() + "-" + System.currentTimeMillis() + "-";
        Thread.sleep(100L);
        ss.close();
      }
      catch (Exception ioe) {
        log.warn("could not generate unique stub", ioe);
      }
    }
    else {
      hostName = "localhost";
      stub = "ID:" + hostName + "-1-" + System.currentTimeMillis() + "-";
    }
    UNIQUE_STUB = stub;
  }
}